import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
import * as container from 'rhea'
import { randomUUID, createHmac } from 'crypto'
import { ConnectOptions } from './type/ConnectOptions';



@Injectable()
export class AmqpClientService{
    private _connection:container.Connection;

    private eventList:any[] = []


    constructor(
		@Inject('AMQP_CONNECT_OPTIONS') private options: ConnectOptions,
	) {
		
	}

    hmacSha1(key, context) {
        return Buffer.from(createHmac('sha1', key).update(context).digest())
            .toString('base64');
    }


    connect() {
        const timestamp = Date.now() / 1000//Math.floor(Date.now() / 1000)


        let username = `${randomUUID()}|authMode=aksign,signMethod=hmacsha1,timestamp=${timestamp},authId=${this.options.accessKeyId}`
        if(this.options.iotInstanceId) {
            username += (`,iotInstanceId=${this.options.iotInstanceId}`)
        }

        username += (`,consumerGroupId=${this.options.consumerGroupId}|`)

        const password = Buffer.from(createHmac('sha1', this.options.accessKeySecret).update('authId='+ this.options.accessKeyId +'&timestamp=' + timestamp).digest()).toString('base64')


        const params:any = {
            //接入域名，请参见AMQP客户端接入说明文档。
            'host': `${this.options.uid}.iot-amqp.${this.options.regionId}.aliyuncs.com`,
            'port': 5671,
            'transport':'tls',
            'reconnect':true,
            'idle_time_out':60000,
            //userName组装方法，请参见AMQP客户端接入说明文档。其中的iotInstanceId，企业版实例请填写实例ID，公共实例直接删除${YourIotInstanceId}。
            'username': username, 
            //计算签名，password组装方法，请参见AMQP客户端接入说明文档。
            'password': password,
        }

        this._connection = container.connect(params)

        while(true) {
            const e = this.eventList.pop()
            if(e) {
                this._connection.on(e[0], e[1])
            }else {
                break
            }
        }

        this._connection.open_receiver()
    }

    get connection() {
        return this._connection
    }

    on(event:string, callback:(...args:any[]) => void) {
        if(!this._connection) {
            this.eventList.push([event, callback])
        }else {
            this._connection.on(event, callback)
        }


        
    }
}
